#include "FleetColonizePlanet.hh"
#include "Done.hh"
#include "XmlServerThread.hh"
#include "../World/Fleet.hh"
#include "../World/Fleet/ColonizePlanet.hh"
#include "../Exception.hh"

#define ERROR(NAME, MESSAGE)                    \
    struct NAME##Invalid {                      \
        void operator() () {                    \
            throw                               \
              NonFatalProtocolError(            \
                "game.fleet_colonize_planet." + \
                QString((MESSAGE)) +" invalid"  \
              );                                \
        }                                       \
    }                                           \

using namespace Network;
using namespace World;

ERROR(FcpFleetId,  "fleet_id");
ERROR(FcpStarId,   "star_id");
ERROR(FcpPlanetId, "planet_id");

spFleetColonizePlanet
FleetColonizePlanet::construct(QDomElement const& message) {
    QDomElement const fleetElem = message.firstChildElement("fleet");
    QDomElement const starElem = message.firstChildElement("star");
    QDomElement const planetElem = message.firstChildElement("planet");
    return spFleetColonizePlanet(
      new FleetColonizePlanet(
        ::parse_num< u8, FcpFleetIdInvalid  >(fleetElem),
        ::parse_num< u8, FcpStarIdInvalid   >(starElem),
        ::parse_num< u1, FcpPlanetIdInvalid >(planetElem)
      )
    );
}

FleetColonizePlanet::FleetColonizePlanet(u8 fleetId, u8 starId, u1 planetId):
    fleetId(fleetId),
    starId(starId),
    planetId(planetId) {}

void FleetColonizePlanet::process_on_server(XmlServerThread& thread) {
    if (thread.get_state() != GAME)
        throw NonFatalProtocolError("game.fleet_colonize_planet unexpected");

    try {
        spPlayer player = thread.get_player();
        spFleet fleet = player->get_fleet(fleetId);
        spPlanet planet =
          player->get_galaxy()->get_star(starId)->get_planet(planetId);
        fleet->set_command(new Fleet::ColonizePlanet(planet));
        Done done(true, "game.fleet_colonize_planet ok");
        done.send_to(*thread.get_socket());
    } catch (FleetNotFound& ex) {
        Done done(false, ex.what());
        done.send_to(*thread.get_socket());
    }
}

QDomDocument FleetColonizePlanet::to_xml() const {
    QDomDocument doc;
    QDomElement gameElem = doc.createElement("game");
    QDomElement fleetColonizePlanetElem =
      doc.createElement("fleet_colonize_planet");
    doc.appendChild(gameElem);
    gameElem.appendChild(fleetColonizePlanetElem);
    ::to_xml(fleetColonizePlanetElem, "fleet",  fleetId);
    ::to_xml(fleetColonizePlanetElem, "star",   starId);
    ::to_xml(fleetColonizePlanetElem, "planet", planetId);
    return doc;
}

#undef ERROR
